--- /dev/null
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+
+ <!--
+ org.gnome.Shell.Introspect:
+ @short_description: Introspection interface
+
+ The interface used to introspect the state of Shell, such as running
+ applications, currently active application, etc.
+ -->
+ <interface name="org.gnome.Shell.Introspect">
+
+ <!--
+ RunningApplicationsChanged:
+ @short_description: Notifies when the running applications changes
+ -->
+ <signal name="RunningApplicationsChanged" />
+
+ <!--
+ GetRunningApplications:
+ @short_description: Retrieves the description of all running applications
+
+ Each application is associated by an application ID. The details of
+ each application consists of a varlist of keys and values. Available
+ keys are listed below.
+
+ 'active-on-seats' - (as) list of seats the application is active on
+ (a seat only has at most one active
+ application)
+ -->
+ <method name="GetRunningApplications">
+ <arg name="apps" direction="out" type="a{sa{sv}}" />
+ </method>
+ </interface>
+</node>
--- /dev/null
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+
+const INTROSPECT_SCHEMA = 'org.gnome.shell';
+const INTROSPECT_KEY = 'introspect';
+const APP_WHITELIST = ['org.freedesktop.impl.portal.desktop.gtk'];
+
+const { loadInterfaceXML } = imports.misc.fileUtils;
+
+const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
+
+var IntrospectService = new Lang.Class({
+ Name: 'IntrospectService',
+
+ _init() {
+ this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(IntrospectDBusIface,
+ this);
+ this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Introspect');
+ Gio.DBus.session.own_name('org.gnome.Shell.Introspect',
+ Gio.BusNameOwnerFlags.REPLACE,
+ null, null);
+
+ this._runningApplications = {};
+ this._runningApplicationsDirty = true;
+ this._activeApplication = null;
+ this._activeApplicationDirty = true;
+
+ this._appSystem = Shell.AppSystem.get_default();
+ this._appSystem.connect('app-state-changed',
+ () => {
+ this._runningApplicationsDirty = true;
+ this._syncRunningApplications();
+ });
+
+ this._settings = new Gio.Settings({ schema_id: INTROSPECT_SCHEMA });
+
+ let tracker = Shell.WindowTracker.get_default();
+ tracker.connect('notify::focus-app',
+ () => {
+ this._activeApplicationDirty = true;
+ this._syncRunningApplications();
+ });
+
+ this._syncRunningApplications();
+ },
+
+ _isStandaloneApp(app) {
+ let windows = app.get_windows();
+
+ return app.get_windows().some(w => w.transient_for == null);
+ },
+
+ _isIntrospectEnabled() {
+ return this._settings.get_boolean(INTROSPECT_KEY);
+ },
+
+ _isSenderWhitelisted(sender) {
+ return APP_WHITELIST.includes(sender);
+ },
+
+ _syncRunningApplications() {
+ let tracker = Shell.WindowTracker.get_default();
+ let apps = this._appSystem.get_running();
+ let seatName = "seat0";
+ let newRunningApplications = {};
+
+ let newActiveApplication = null;
+ let focusedApp = tracker.focus_app;
+
+ for (let app of apps) {
+ let appInfo = {};
+ let isAppActive = (focusedApp == app);
+
+ if (!this._isStandaloneApp(app))
+ continue;
+
+ if (isAppActive) {
+ appInfo['active-on-seats'] = new GLib.Variant('as', [seatName]);
+ newActiveApplication = app.get_id();
+ }
+
+ newRunningApplications[app.get_id()] = appInfo;
+ }
+
+ if (this._runningApplicationsDirty ||
+ (this._activeApplicationDirty &&
+ this._activeApplication != newActiveApplication)) {
+ this._runningApplications = newRunningApplications;
+ this._activeApplication = newActiveApplication;
+
+ this._dbusImpl.emit_signal('RunningApplicationsChanged', null);
+ }
+ this._runningApplicationsDirty = false;
+ this._activeApplicationDirty = false;
+ },
+
+ GetRunningApplicationsAsync(params, invocation) {
+ if (!this._isIntrospectEnabled() &&
+ !this._isSenderWhitelisted(invocation.get_sender())) {
+ invocation.return_error_literal(Gio.DBusError,
+ Gio.DBusError.ACCESS_DENIED,
+ 'App introspection not allowed');
+ return;
+ }
+
+ invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
+ }
+});
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const InputMethod = imports.misc.inputMethod;
+const Introspect = imports.misc.introspect;
const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
var layoutManager = null;
var kbdA11yDialog = null;
var inputMethod = null;
+var introspectService = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
+ introspectService = new Introspect.IntrospectService();
+
layoutManager.init();
overview.init();